package com.frejoys.service.impl;


import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.frejoys.common.dto.admin.DelIdDto;
import com.frejoys.common.dto.common.auth.*;
import com.frejoys.common.enums.EStatus;
import com.frejoys.common.error.HttpStatus;
import com.frejoys.common.exception.GeneralException;
import com.frejoys.dao.entity.AuthGroup;
import com.frejoys.dao.entity.AuthGroupAccess;
import com.frejoys.dao.entity.AuthRule;
import com.frejoys.dao.entity.Category;
import com.frejoys.dao.mapper.AuthGroupAccessMapper;
import com.frejoys.dao.mapper.AuthGroupMapper;
import com.frejoys.service.AuthGroupAccessService;
import com.frejoys.service.AuthGroupService;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;


@Service
@RequiredArgsConstructor
public class AuthGroupServiceImpl extends ServiceImpl<AuthGroupMapper, AuthGroup> implements AuthGroupService {

    private final AuthGroupAccessService authGroupAccessService;

    private final AuthGroupAccessMapper authGroupAccessMapper;

    @Override
    public Boolean addInfo(AuthGroupAddDto dto) {

        String path = "0";
        if (!dto.getPid().equals(0)) {
            AuthGroup pAG = getById(dto.getPid());
            path = pAG.getPath() + "," + pAG.getId();
        }

        String finalPath = path;

        return save(new AuthGroup(){{
            setName(dto.getName());
            setRules(dto.getRules());
            setPid(dto.getPid());
            setPath(finalPath);
        }});
    }

    @Override
    public Boolean upInfo(AuthGroupUpDto dto) {
        LambdaUpdateWrapper<AuthGroup> wrapper = new UpdateWrapper().lambda();
        wrapper.eq(AuthGroup::getId, dto.getId());

        if (StrUtil.isNotEmpty(dto.getName())) {
            wrapper.set(AuthGroup::getName, dto.getName());
        }

        if (StrUtil.isNotEmpty(dto.getRules())) {
            wrapper.set(AuthGroup::getRules, dto.getRules());
        }
        if (dto.getPid() != null) {
            // 判断
            if (dto.getPid().equals(0)) {
                wrapper.set(AuthGroup::getPid, dto.getPid());
                wrapper.set(AuthGroup::getPath, dto.getPid());
            } else {
                // pid和原pid是否一致
                LambdaQueryWrapper<AuthGroup> authGroupLambdaQueryWrapper = new LambdaQueryWrapper<>();
                authGroupLambdaQueryWrapper.select(AuthGroup::getPid).eq(AuthGroup::getId, dto.getId());
                AuthGroup sAG = getOnly(authGroupLambdaQueryWrapper);
                if (!dto.getPid().equals(sAG.getPid())) {
                    // 新pid
                    LambdaQueryWrapper<AuthGroup> nAuth = new LambdaQueryWrapper<>();
                    nAuth.select(AuthGroup::getPath).eq(AuthGroup::getId, dto.getPid());
                    AuthGroup nAR = getOnly(nAuth);
                    wrapper.set(AuthGroup::getPid, dto.getPid());
                    wrapper.set(AuthGroup::getPath, nAR.getPath() + "," + dto.getPid());
                }
            }
        }

        return update(wrapper);
    }

    @Override
    public Boolean addRule(AuthGroupRulesAddDto dto) {
        LambdaUpdateWrapper<AuthGroup> wrapper = new UpdateWrapper().lambda();
        wrapper.eq(AuthGroup::getId, dto.getId());

        // 获取当前权限
        String rules = getRulesInfo(dto.getId());
        String[] rulesA = rules.split(",");
        String[] rulesB = dto.getRules().split(",");
        // 合并新旧权限
        String[] rulesNew = ArrayUtil.addAll(rulesA, rulesB);
        String str = ArrayUtil.join(Arrays.stream(rulesNew).distinct().sorted().toArray(), ",");
        str = StrUtil.removePrefix(str, ",");
        str = StrUtil.removeSuffix(str, ",");
        wrapper.set(AuthGroup::getRules, str);

        return update(wrapper);
    }

    @Override
    public Boolean reduceRule(AuthGroupRulesAddDto dto) {
        LambdaUpdateWrapper<AuthGroup> wrapper = new UpdateWrapper().lambda();
        wrapper.eq(AuthGroup::getId, dto.getId());

        // 获取当前权限
        String rules = getRulesInfo(dto.getId());

        if (StrUtil.isEmpty(rules)) {
            return true;
        }

        String[] rulesA = rules.split(",");
        String[] rulesB = dto.getRules().split(",");
        List<String> rulesLA = Arrays.stream(rulesA).collect(Collectors.toList());
        List<String> rulesLB = Arrays.stream(rulesB).collect(Collectors.toList());

        List<String> finalRules = new ArrayList<>();

        if (rulesA.length > rulesB.length) {
            rulesLA.removeAll(rulesLB);
            finalRules = rulesLA;
        } else {
            rulesLB.removeAll(rulesLA);
            finalRules = rulesLB;
        }

        String str = ArrayUtil.join(finalRules.toArray(), ",");
        str = StrUtil.removePrefix(str, ",");
        str = StrUtil.removeSuffix(str, ",");
        wrapper.set(AuthGroup::getRules, str);
        return update(wrapper);
    }

    @Override
    public String getRulesInfo(Integer id) {
        LambdaQueryWrapper<AuthGroup> wrapper = new QueryWrapper().lambda();
        wrapper.select(AuthGroup::getRules).eq(AuthGroup::getId, id);
        AuthGroup group = getOnly(wrapper);
        return group == null ? "" : group.getRules();
    }

    @Override
    public IPage<AuthGroup> listInfo(Long userId, AuthGroupListDto dto) {
        Page page = new Page<>(dto.getPage(), dto.getSize());
        // 查询超级管理员权限
        List<AuthGroupAccess> userGroupList = authGroupAccessService.getListByUserId(userId);
        boolean hasAdminRole = userGroupList.stream().anyMatch(authGroupAccess -> authGroupAccess.getGroupId().equals(1));
        LambdaQueryWrapper<AuthGroup> wrapper = new QueryWrapper().lambda();
        return baseMapper.selectPage(page,wrapper);
    }

    @Override
    public List<AuthRule> filterRule(Long userId, List<AuthRule> rules) {
        List<AuthRule> list = new ArrayList<>();

        List<String> ruleList = listUserGroupRules(userId);
        if (!ruleList.isEmpty()) {

            rules.forEach( e -> {

                if (ruleList.contains(e.getId().toString())) {
                    list.add(e);
                }

            });

        }

        return list;
    }

    @Override
    public List<String> getUserGroupRules(Long userId) {
        List<String> list = new ArrayList<>();
        // 用户组关联
        List<AuthGroupAccess> access = authGroupAccessService.getListByUserId(userId);
        if (!access.isEmpty()) {
            // 获取用户权限组关联
            List<Integer> groupIds = access.stream().map(AuthGroupAccess::getGroupId).collect(Collectors.toList());

            // 获取权限角色包含的权限
            List<AuthGroup> groups = listGroupById(groupIds);
            Object[] rulesList = groups.stream().map(AuthGroup::getRules).filter(Objects::nonNull).filter(e -> !"".equals(e)).toArray();
            list = Arrays.stream(ArrayUtil.join(rulesList, ",").split(",")).distinct().collect(Collectors.toList());
        }
        return list;
    }

    @Override
    public List<AuthGroup> listGroupById(List<Integer> ids) {
        LambdaQueryWrapper<AuthGroup> wrapper = new QueryWrapper().lambda();
        wrapper.in(AuthGroup::getId, ids).eq(AuthGroup::getStatus, EStatus.on.getValue());
        return list(wrapper);
    }

    @Override
    public List<String> listUserGroupRules(Long userId) {
        List<String> list = new ArrayList<>();
        // 用户组关联
        List<AuthGroupAccess> access = authGroupAccessService.getListByUserId(userId);
        if (!access.isEmpty()) {
            // 获取用户权限组关联
            List<Integer> groupIds = access.stream().map(e -> e.getGroupId()).collect(Collectors.toList());

            // 获取权限角色包含的权限
            List<AuthGroup> groups = listGroupById(groupIds);
            Object[] rulesList = groups.stream().map(e -> e.getRules()).filter(Objects::nonNull).filter(e -> !"".equals(e)).toArray();
            list = Arrays.stream(ArrayUtil.join(rulesList, ",").split(",")).distinct().collect(Collectors.toList());
        }
        return list;
    }

    @Override
    public Map<Long, String> mapUserGroupRules(List<Long> userId) {
        return null;
    }

    @Override
    public List<AuthGroup> listUserGroupTitle(List<Integer> ids) {
        return null;
    }

    @Override
    public boolean authRuleAuthorize(AuthGroupAuthorizeDto dto) {
        authGroupAccessService.deleteByUserId(dto.getUserId());
        for (Integer groupId : dto.getGroupId()) {
            authGroupAccessService.addInfo(dto.getUserId(), groupId);
        }
        return true;
    }


    @Override
    public boolean deleteAuthRule(DelIdDto dto) {

        if (dto.getStatus() == EStatus.off.getValue()){
            LambdaQueryWrapper<AuthGroupAccess> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.select(AuthGroupAccess::getUserId).eq(AuthGroupAccess::getGroupId,dto.getId());
            List<AuthGroupAccess> accessList = authGroupAccessMapper.selectList(queryWrapper);

            if (!accessList.isEmpty()){
                throw new GeneralException(HttpStatus.authGroupAccessDelError);
            }
        }

        LambdaUpdateWrapper<AuthGroup> wrapper = new LambdaUpdateWrapper<>();
            wrapper.eq(AuthGroup::getId, dto.getId());
            wrapper.set(AuthGroup::getStatus,dto.getStatus());
            return update(wrapper);
    }
}
